package com.zackeus.mvvm.base;

import android.app.Activity;
import android.app.Application;
import android.os.Bundle;

import androidx.annotation.NonNull;

import com.elvishew.xlog.LogConfiguration;
import com.elvishew.xlog.LogLevel;
import com.elvishew.xlog.XLog;
import com.elvishew.xlog.printer.AndroidPrinter;
import com.elvishew.xlog.printer.Printer;
import com.elvishew.xlog.printer.file.FilePrinter;
import com.elvishew.xlog.printer.file.backup.NeverBackupStrategy;
import com.elvishew.xlog.printer.file.clean.FileLastModifiedCleanStrategy;
import com.elvishew.xlog.printer.file.naming.FileNameGenerator;
import com.hjq.toast.ToastUtils;
import com.liulishuo.okdownload.OkDownload;
import com.liulishuo.okdownload.core.connection.DownloadOkHttp3Connection;
import com.liulishuo.okdownload.core.file.HotFixedProcessFileStrategy;
import com.zackeus.common.utils.Utils;
import com.zackeus.mvvm.api.SSLSocketManager;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.TimeZone;

import okhttp3.OkHttpClient;

public abstract class BaseApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        initApplication(this);

        //初始化工具类
        Utils.init(this);
        /* 初始化 Toast 框架 */
        ToastUtils.init(this);
        /* 初始化日志 */
        initLog();
        /* 初始化下载引擎 */
        initDownload();
    }

    /**
     * 日志级别
     * @return
     */
    protected int logLevel() {
        return LogLevel.ERROR;
    }

    /**
     * 日志配置
     * @return
     */
    @NonNull
    protected LogConfiguration logConfig() {
        return new LogConfiguration.Builder()
                /* 指定日志级别，低于该级别的日志将不会被打印，默认为 LogLevel.ERROR */
                .logLevel(this.logLevel())
                /* 允许打印线程信息，默认禁止 */
                .enableThreadInfo()
                /* 允许打印深度为 2 的调用栈信息，默认禁止 */
                .enableStackTrace(2)
                /* 允许打印日志边框，默认禁止 */
                .enableBorder()
                .build();
    }

    /**
     * 日志打印器
     * @return
     */
    @NonNull
    protected List<Printer> logPrinters() {
        List<Printer> printers = new ArrayList<>();

        Printer androidPrinter = new AndroidPrinter(Boolean.TRUE);
        Printer filePrinter = new FilePrinter
                /* 指定保存日志文件的路径 */
                .Builder(this.getExternalFilesDir(null).getPath() + "/Log")
                .fileNameGenerator(new FileNameGenerator() {
                    /* 指定日志文件名生成器，默认为 ChangelessFileNameGenerator("log") */
                    final ThreadLocal<SimpleDateFormat> mLocalDateFormat = new ThreadLocal<>() {
                        @Override
                        protected SimpleDateFormat initialValue() {
                            return new SimpleDateFormat("yyyy-MM-dd", Locale.US);
                        }
                    };

                    @Override
                    public boolean isFileNameChangeable() {
                        return Boolean.TRUE;
                    }

                    @Override
                    public String generateFileName(int logLevel, long timestamp) {
                        SimpleDateFormat sdf = this.mLocalDateFormat.get();
                        assert sdf != null;
                        sdf.setTimeZone(TimeZone.getDefault());
                        return sdf.format(new Date(timestamp)) + ".log";
                    }
                })
                /* 日志文件备份策略，默认为 FileSizeBackupStrategy(1024 * 1024) */
                .backupStrategy(new NeverBackupStrategy())
                /* 日志文件清除策略，默认为 NeverCleanStrategy() */
                .cleanStrategy(new FileLastModifiedCleanStrategy(3*24*60*60*1000))
                .build();

        printers.add(androidPrinter);
        printers.add(filePrinter);
        return printers;
    }

    /**
     * 日志初始化
     */
    private void initLog() {
        XLog.init(logConfig(), logPrinters().toArray(new Printer[0]));
    }

    /**
     * 文件下载网路请求工厂
     * @return
     */
    @NonNull
    protected DownloadOkHttp3Connection.Factory downloadConnectionFactory() {
        SSLSocketManager.SSLParams sslParams = SSLSocketManager.getSslSocketFactory();
        OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder()
                /* 忽略不信任证书 */
                .sslSocketFactory(sslParams.sSLSocketFactory, sslParams.trustManager)
                .hostnameVerifier(SSLSocketManager.UnSafeHostnameVerifier)
                /* 允许重定向 */
                .followRedirects(Boolean.TRUE)
                .followSslRedirects(Boolean.TRUE)
                .retryOnConnectionFailure(Boolean.FALSE);
        DownloadOkHttp3Connection.Factory factory = new DownloadOkHttp3Connection.Factory();
        factory.setBuilder(clientBuilder);
        return factory;
    }

    /**
     * 下载引擎初始化
     */
    private void initDownload() {
        OkDownload.Builder builder = new OkDownload.Builder(this)
                /* 网络请求框架 */
                .connectionFactory(downloadConnectionFactory())
                .processFileStrategy(new HotFixedProcessFileStrategy());
        /* 只能执行一次 */
        OkDownload.setSingletonInstance(builder.build());
    }

    private synchronized void initApplication(@NonNull Application application) {
        //注册监听每个activity的生命周期,便于堆栈式管理
        application.registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {

            @Override
            public void onActivityCreated(@NonNull Activity activity, Bundle savedInstanceState) {
                AppManager.getAppManager().addActivity(activity);
            }

            @Override
            public void onActivityStarted(@NonNull Activity activity) {
                AppManager.getAppManager().addVisible();
            }

            @Override
            public void onActivityResumed(@NonNull Activity activity) {
            }

            @Override
            public void onActivityPaused(@NonNull Activity activity) {
            }

            @Override
            public void onActivityStopped(@NonNull Activity activity) {
                AppManager.getAppManager().reduceVisible();
            }

            @Override
            public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState) {
            }

            @Override
            public void onActivityDestroyed(@NonNull Activity activity) {
                AppManager.getAppManager().removeActivity(activity);
            }
        });
    }

    @Override
    public void onTerminate() {
        super.onTerminate();
        /* 取消所有下载任务 */
        OkDownload.with().downloadDispatcher().cancelAll();
    }
}
